package org.springblade.modules.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.modules.admin.dto.parts.BatchRelationCategoryDTO;
import org.springblade.modules.admin.entity.ElevatorPartsStructureTemplateRelation;
import org.springblade.modules.admin.entity.PartsInfo;
import org.springblade.modules.admin.entity.RelationAlias;
import org.springblade.modules.admin.service.*;
import org.springblade.modules.admin.vo.MaintainPartsTreeVO;
import org.springblade.modules.admin.vo.MaintainPartsVO;
import org.springblade.modules.admin.vo.MaintainPartsWithAttributesTreeVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springblade.modules.admin.entity.MaintainParts;
import org.springblade.modules.admin.mapper.MaintainPartsMapper;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class MaintainPartsServiceImpl extends BaseServiceImpl<MaintainPartsMapper, MaintainParts> implements MaintainPartsService{

	@Autowired
	private RelationAliasService relationAliasService;
	@Autowired
	private IElevatorPartsStructureTemplateRelationService elevatorPartsStructureTemplateRelationService;
	@Autowired
	private IMaintainPartsAttributeRelationService attributeRelationService;

	@Override
	public List<MaintainPartsVO> partsList(MaintainParts maintainParts) {
		return baseMapper.partsList(maintainParts);
	}

	@Override
	public List<MaintainPartsTreeVO> partsTree(MaintainParts maintainParts) {
		return baseMapper.partsTree(maintainParts);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public boolean submit(MaintainParts maintainParts) {
		if (Func.isEmpty(maintainParts.getParentId())) {
			maintainParts.setTenantId(AuthUtil.getTenantId());
			maintainParts.setParentId(BladeConstant.TOP_PARENT_ID);
			maintainParts.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID));
		}

		if (maintainParts.getParentId() > 0) {
			MaintainParts parent = getById(maintainParts.getParentId());
			if (Func.toLong(maintainParts.getParentId()) == Func.toLong(maintainParts.getId())) {
				throw new ServiceException("父节点不可选择自身!");
			}
			String ancestors = parent.getAncestors() + StringPool.COMMA + maintainParts.getParentId();
			maintainParts.setAncestors(ancestors);
			maintainParts.setLevel(Func.toLongList(ancestors).size());
		}

		// 重复校验
		LambdaQueryWrapper<MaintainParts> condition = Wrappers.<MaintainParts>lambdaQuery()
			.eq(MaintainParts :: getName, maintainParts.getName())
			.eq(MaintainParts :: getParentId, maintainParts.getParentId());
		if (Func.isNotEmpty(maintainParts.getId())) {
			condition.ne(MaintainParts :: getId, maintainParts.getId());
		}
		int checkRepeat = count(condition);
		if (checkRepeat > 0) {
			throw new ServiceException("该类别已存在!");
		}

		if (Func.equalsSafe(maintainParts.getStructureType(), 1)) {
			maintainParts.setCategoryId(null);
			maintainParts.setCategoryInfo(null);
		}

		if (saveOrUpdate(maintainParts)) {
			aliasHandler(maintainParts.getId(), maintainParts.getAliasList());
			// 2024-10-14 新增 配件维保属性关联
			List<Long> attributeIdList = maintainParts.getAttributeIdList();

			Long id = maintainParts.getId();
			attributeRelationService.addPartsAttributeRelation(id, attributeIdList);

			return true;
		}

		return false;

	}

	/**
	 * 别名处理
	 * @param partsId
	 * @param aliasList
	 */
	private void aliasHandler(Long partsId, List<String> aliasList) {
		List<RelationAlias> relationAliasList = relationAliasService.list(Wrappers.<RelationAlias>lambdaQuery().eq(RelationAlias :: getRelationId, partsId));
		if (Func.isNotEmpty(relationAliasList)) {
			relationAliasService.deleteLogic(relationAliasList.stream().map(BaseEntity::getId).collect(Collectors.toList()));
		}

		if (Func.isNotEmpty(aliasList)) {
			List<RelationAlias> relationAliasListNew = new ArrayList<>();
			for (String alias : aliasList) {
				RelationAlias relationAlias = new RelationAlias();
				relationAlias.setRelationId(partsId);
				relationAlias.setAlias(alias);
				relationAliasListNew.add(relationAlias);
			}
			relationAliasService.saveBatch(relationAliasListNew);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean removeParts(List<Long> ids) {
		LambdaQueryWrapper<MaintainParts> condition = Wrappers.<MaintainParts>lambdaQuery();
		for (int i = 0; i < ids.size(); i++) {
			condition.like(MaintainParts :: getAncestors, ids.get(i)).or();
		}
		int checkChild = count(condition);
		if (checkChild > 0) {
			throw new ServiceException("删除配件类别失败，请先删除子级");
		}

//		int check = partsInfoService.count(Wrappers.<PartsInfo>lambdaQuery().in(PartsInfo :: getMaintainPartsId, ids));
//		if (check > 0) {
//			throw new ServiceException("删除配件类别失败，类别已有配件信息");
//		}
		return deleteLogic(ids);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean batchRelationCategory(BatchRelationCategoryDTO param) {
		if (Func.isEmpty(param.getPartsIds())) {
			return false;
		}

		List<MaintainParts> updateList = new ArrayList<>();
		param.getPartsIds().forEach(partsId -> {
			MaintainParts maintainParts = new MaintainParts();
			maintainParts.setId(partsId);
			maintainParts.setCategoryId(param.getCategoryId());
			maintainParts.setCategoryInfo(param.getCategoryInfo());
			updateList.add(maintainParts);
		});

		return this.updateBatchById(updateList);
	}

	@Override
	public List<MaintainPartsTreeVO> getElevatorStructureTree(Long elevatorId) {
		ElevatorPartsStructureTemplateRelation templateRelation = elevatorPartsStructureTemplateRelationService.getOne(Wrappers.<ElevatorPartsStructureTemplateRelation>lambdaQuery().eq(ElevatorPartsStructureTemplateRelation :: getElevatorId, elevatorId), false);
		if (Func.isEmpty(templateRelation) || Func.isEmpty(templateRelation.getCategoryArrIds())) {
			return new ArrayList<>();
		}

		List<MaintainPartsTreeVO> childList = baseMapper.getPartsChildList(templateRelation.getCategoryArrIds(), elevatorId);
		// 父节点id集合
		Set<String> parentIds = childList.stream().map(MaintainPartsTreeVO::getAncestors).flatMap(t -> Arrays.stream(t.split(StringPool.COMMA))).collect(Collectors.toSet());
		List<MaintainPartsTreeVO> parentList = baseMapper.getPartsParentByIds(parentIds, elevatorId);

		// childList+parentList两个集合合并，并去重
		childList.addAll(parentList);
		return childList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MaintainPartsTreeVO::getId))), ArrayList::new));
	}

	/**
	 * 处理历史ancestors与level数据
	 * @return
	 */
	@Override
	public boolean initData() {
		List<MaintainParts> list = baseMapper.selectAll();
		if (Func.isEmpty(list)) {
			return true;
		}

		List<MaintainParts> updateList = new ArrayList<>();
		Map<Long, MaintainParts> map = list.stream().collect(Collectors.toMap(t -> t.getId(), t -> t));
		for (MaintainParts maintainParts : list) {
			StringBuilder ancestors = new StringBuilder();
			Long parentId = maintainParts.getParentId();
			while (parentId > 0) {
				ancestors.insert(0, String.valueOf(StringPool.COMMA + parentId));
				MaintainParts child = map.get(parentId);
				parentId = child.getParentId();
			}
			ancestors.insert(0, String.valueOf(BladeConstant.TOP_PARENT_ID));
			maintainParts.setAncestors(ancestors.toString());
			maintainParts.setLevel(Func.toLongList(ancestors.toString()).size());
			updateList.add(maintainParts);
		}

		return updateBatchById(updateList);
	}

	@Override
	@TenantIgnore
	public List<MaintainPartsWithAttributesTreeVO> partsTreeWithAttributes(MaintainParts maintainParts) {
		return baseMapper.partsTreeWithAttributes(maintainParts);
	}

	@Override
	public boolean removePartsByIds(List<Long> partsIdList) {
		return this.removeByIds(partsIdList);
	}
}
